/**
 * Copyright (c) 2010 Basil Shikin, LegoCamera Project
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.legocam;

/**
 * This class contains functions that measure how much film should be winded.
 * <p>
 * Following model is used:
 *  <pre>
 *      // - \\
 *     ||  +---+ = r0 + th (reel radius + film thickness)
 *      \\ _ //
 *  </pre>
 *  
 *  So, basic formula that gives relation between film length and reel roation number is:
 *  
 *  <pre>
 *          L(n) = pi*th*n^2 + 2*pi*r0*(n+1), where
 *
 *             L - length of film
 *             n - number of rations
 *             th - film thickness
 *             r0 - reel radius
 * <pre>
 *  
 * @author Basil Shikin
 *
 */
public class FilmTransportUtils
{
	public static final float REEL_RADIUS = 7F; // mm. (assume there is some film over it already)  
	public static final float FILM_THICKNESS = 0.2F; // mm.
	public static final int SNAPSHOT_OFFSET_LENGTH = 45; // mm.
	
	public static int calculatePrimaryReelRotationAngle( int snapshotsNumber, int maxSnapshots )
	{
		int f = SNAPSHOT_OFFSET_LENGTH;
		
		return filmLengthToAngle( ( snapshotsNumber + 1 )*f ) - filmLengthToAngle( snapshotsNumber*f );
	}
	
	public static int calculateSecondaryReelRotationAngle( int snapshotsNumber, int maxSnapshots )
	{
		int f = SNAPSHOT_OFFSET_LENGTH;
		
		return filmLengthToAngle( (maxSnapshots - snapshotsNumber )*f ) - filmLengthToAngle( (maxSnapshots - snapshotsNumber - 1 )*f );
	}
	
	public static int calculateRewindAngle( int filmSize )
	{
		int f = SNAPSHOT_OFFSET_LENGTH;
		
		return filmLengthToAngle( f*(filmSize-1) );
	}
	
	protected static int filmLengthToAngle( int filmLength )
	{
		float th =  FILM_THICKNESS;
		float r0 =  REEL_RADIUS;
		
		// Calculate number of roations for the
		double res = ( Math.sqrt( r0*r0 + ( th*filmLength )/Math.PI ) - r0 )/th;
		
		return (int)Math.round(360*res );
	}
	
	public static void main(String[] args)
	{
		System.out.println( "REW 24: " + calculateRewindAngle( 24 ) );
		
		System.out.println( " REW PRI 1: " + calculatePrimaryReelRotationAngle( 0, 24) );
		System.out.println( "REW SEC 1: " + calculateSecondaryReelRotationAngle( 0, 24 ) );
		
		int pA =  0;
		int sA = calculateRewindAngle( 24 );
		
		for ( int i = 1; i < 24; i ++ )
		{
			pA += calculatePrimaryReelRotationAngle( i, 24);
			sA -= calculateSecondaryReelRotationAngle( i, 24 );
			
			System.out.println( "PRI 1: " + calculatePrimaryReelRotationAngle( i, 24) );
			System.out.println( "SEC 1: " + calculateSecondaryReelRotationAngle( i,24 ) );
		}
		
		System.out.println( " AFTER PRI: " + pA );
		System.out.println( " AFTER SEC: " + sA );
	}
}
